



# B+树 多叉树， 每个节点 16k 的数据页，能存储特别多的索引信息，扇出很高，每个索引页指向1000多个子页
# 3层左右可以存储2000万左右数据，如果查询数据都在磁盘里，这些数据最多需要3次磁盘io

# 跳表，链式结构，2000万数据，如果需要达到2分效果，需要24次方，查一次数据需要接力24次磁盘io

# 写入操作 b+树 需要拆分索引也， 调表直接插入，没有旋转和维持平衡的开销，写入性能比B+树好很多

#  -------------------------  计算3层B+树存储上线  ---------------------
# 非叶子节点每个  假设能 有 15k 存放数据， 每个数据包括  主键和只想页号的索引构成
# 主键 bigint 8字节，页号 4字节 ----->  非叶子节点一个数据 12字节    15k / 12 = 1280
# 叶子节点类似： 如果一条行数据 占 1k  能放 15 条
# 3层B+树能存放数据为   1280 的 3 - 1 次方 * 15  为 2500w
# 如果单行 数据大小 250个字节，那么单节点 能放60 条数据，3层B+树页就能支持 1亿数据量









#  -------------------------  几种日志  ---------------------
# Binlog (二进制日志) 功能：记录所有修改数据的 SQL 语句（DDL 和 DML）主要用于主从复制和数据恢复
# 特点：
# 服务器级别日志，所有存储引擎都适用
# 有三种格式：STATEMENT(语句)、ROW(行)、MIXED(混合)
# 通过 max_binlog_size 设置单个文件大小
# 通过 expire_logs_days 设置过期时间



# Undo Log (回滚日志)功能：记录事务发生前的数据状态，用于事务回滚和 MVCC (多版本并发控制)
# 特点：
# InnoDB 特有
# 存储在系统表空间的回滚段(rollback segment)中
# 逻辑日志，记录与事务相反的SQL操作
# 事务提交后不会立即删除，可能用于MVCC



# Redo Log (重做日志)功能：记录事务对数据页的物理修改，用于崩溃恢复(crash-safe)
# 特点：
# InnoDB 特有
# 物理日志，记录"在某个数据页上做了什么修改"
# 循环写入方式，固定大小
# 通过 innodb_log_file_size 和 innodb_log_files_in_group 配置
# 写入策略由 innodb_flush_log_at_trx_commit 控制



# Relay Log (中继日志)功能：主从复制，从服务器从主服务器接收的binlog保存在relay log中，从服务器的SQL线程读取relay log中的事件并重放
# 特点：
# 格式与binlog相同
# 默认位置在数据目录下
# 通过 relay_log 参数配置名称
# 通过 relay_log_purge 控制是否自动清理




#  ===========优化步骤---------
# 识别慢查询: 使用 slow_query_log。
# 添加适当索引: 针对查询条件添加索引。
# 重写查询: 尝试不同的查询方式或使用表连接。
# 利用EXPLAIN: 理解 SQL 查询的执行过程

# 使用索引：为频繁查询的列创建索引。
# 避免SELECT *：只选择所需的列减少数据传输。
# 使用JOIN而非子查询：在许多情况下，JOIN比子查询更高效。
# 分析查询：使用EXPLAIN命令查看查询的执行计划。
# 限制结果集：通过LIMIT减少返回的数据量。

# 事务: 确保一组操作作为一个原子单元被执行，要么全部成功，要么全部失败，以保持数据的一致性

# 事务的aciid
# 原子性 (Atomicity)：事务中的所有操作要么全部完成，要么全部不做。
# 一致性 (Consistency)：事务执行前后，数据库的完整性约束需得到满足。
# 隔离性 (Isolation)：并发执行的事务互不干扰，每个事务的执行结果对其他事务不可见，直到该事务提交。
# 持久性 (Durability)：一旦事务被提交，对数据库的修改是永久的，即使系统崩溃，数据也不会丢失


# 事务支持：
# InnoDB支持ACID事务。
# MyISAM不支持事务。
# 锁机制：
# InnoDB使用行级锁，提高了并发性能。
# MyISAM使用表级锁，可能导致性能瓶颈。
# 外键支持：
# InnoDB支持外键约束，用于数据完整性。
# MyISAM不支持外键。
# 性能：
# MyISAM在读取较多的场景下性能更优。
# InnoDB在高并发和大型事务中性能表现更好。


# 逻辑备份：使用SQL文件导出数据库结构和数据（如mysqldump）。备份较小，易于维护，但恢复速度可能较慢。
# 物理备份：复制数据库文件（如datadir目录），可快速恢复，但需确保正确的数据库状态进行备份。

# CREATE INDEX idx_salary ON employees (salary);  ---- 在salary列上创建一个索引

# 高并发情况下安全地修改同一行数据
# 行级锁：只锁定被修改的行，使其他操作可以继续。
# 乐观锁：基于版本号或时间戳，检测数据是否被修改，进行冲突检测。
# 悲观锁：在操作前获取锁，直到操作完成，避免其他事务访问。


# 避免LIMIT 10000, 10（扫描10010行），改用WHERE id > last_id LIMIT 10
# 不要在索引列上使用!=、NOT IN、IS NULL。
# 避免LIKE '%xxx%'（前导通配符会使索引失效）
# 避免在索引列上使用函数（如WHERE DATE(create_time) = '2023-01-01'）。
# 优化 JOIN 操作：
#     确保关联字段有索引。
#     小表驱动大表（如JOIN user ON order.user_id = user.id，user表应较小）。
# 索引选择策略：
#     高选择性字段适合建索引（如user_id比gender更适合）。
#     避免过多索引，影响写入性能。



# 创建唯一约束(UNIQUE)防止后续插入重复数据
"""
SELECT email, COUNT(*) AS count FROM customer_emails 
GROUP BY email 
HAVING count > 1;

ALTER TABLE customer_emails ADD CONSTRAINT unique_email UNIQUE (email);
"""
# 外键约束规定某列或多列的值必须在另一个表的主键或唯一列中存在，确保数据的一致性和完整性



# 数据库的三大范式  用于减少冗余和防止数据异常的原则。
# 第一范式 (1NF)：确保表中每个列只保存原子值，避免重复列和多值属性。
# 第二范式 (2NF)：在满足1NF的基础上，每个非主键列必须完全依赖于主键。
# 第三范式 (3NF)：在满足2NF的基础上，非主键列不能依赖于其他非主键列。


# 管理分布式数据库需要使用分片、复制和一致性协议等技术，以实现数据的分布和冗余存储     -----------------------------------------
# 管理分布式数据库的工具，如基于Zookeeper的分布式锁和协调服务，保障多个节点数据的一致性。
# 分布式事务用于保证跨多个数据库的操作要么全部成功，要么全部回滚，以保持数据的一致性
    # 实现分布式事务通常使用两阶段提交协议（2PC）或更复杂的分布式事务管理器（如XA）来协调参与方的成功或失败


# 索引的优缺点和类型
# 优点:
# 加快查询速度，特别是对于大型表。
# 用于唯一性约束（如PRIMARY KEY和UNIQUE索引）。
# 缺点:
# 增加写操作的成本（INSERT、UPDATE、DELETE）因为需要更新索引。
# 占用额外的存储空间。
# 过多索引可能导致性能下降，尤其是在更新频繁的表中。
# 类型:
# B-Tree索引: 默认索引类型，适用于范围查询。
# 哈希索引: 适用于等值查询，只能用于Memory存储引擎。
# 全文索引: 用于文本搜索（如FULLTEXT）。
# 空间索引: 用于处理地理数据。


# 处理和优化大型UPDATE操作: 可以减少锁竞争，提高系统响应速度，避免长时间的阻塞


# 主从实操：https://blog.csdn.net/qq_41786285/article/details/109304126
# 复制延迟的原因包括网络延迟、从服务器负载过重、慢查询等，可以通过监控Seconds_Behind_Master状态变量来检查延迟。
# SHOW SLAVE STATUS\G;  -- 查看详细的从服务器状态
# 分区表是一种将数据表分成不同部分的策略，可以提高查询性能，降低维护成本。
# 减少查询数据量，提高查询效率
# RANGE ：如日期，数值区间 必须是主键/唯一键的一部分。优先选择高基数、频繁用于查询条件的列（如时间戳）。
# 按固定类别（区域、状态）	LIST
# 必须是主键/唯一键的一部分。
# 优先选择高基数、频繁用于查询条件的列（如时间戳）。


# 分布式架构通常涉及到以下几种复制策略
# 主从复制：一个主数据库可以有多个从数据库，从数据库不断从主数据库复制更新，适用于读负载分担。
# 主主复制：两个主数据库互相复制，根据负载情况分担写操作，适合多个地理位置的数据库。
# 半同步复制：主库在确认至少有一个从库接收到数据后，才认为操作成功，增强数据的可靠性。
# 数据分片（Sharding）：将数据水平分割，通过不同的数据库存储，允许更好的负载分配与扩展。


# MySQL通过多个机制处理并发连接，包括：
# 线程池：管理数据库线程，有效地使用连接资源。
# 连接限制：可以通过参数（如max_connections）限制最大连接数，防止资源耗尽。
# 锁机制：使用行级锁或表级锁来处理数据的并发访问，确保数据的一致性。
# 查询缓存：在适当的情况下，缓存查询结果而不必每次都重新处理相同的请求。



# 优化大表的常见方法包括：
# 索引：在查询频繁的列上创建索引。
# 分区：使用分区表方式减少每次查询的数据量。
# 数据归档：定期归档历史数据，减少表的大小。




# 索引优化（解决90%性能问题）
# 最左前缀匹配	
#         联合索引(status, create_time)优化WHERE status='paid' AND create_time > '2023-01-01'	
#         避免全表扫描，提升范围查询效率
# 覆盖索引	SELECT id, name → 索引包含(id, name)列   	避免回表，减少I/O
# 高选择性字段优先   	对区分度>90%的字段（如user_id）建索引 显著降低扫描行数
# 避免索引失效	禁止在WHERE中对字段使用函数（如YEAR(create_time)=2023） 	防止索引失效导致全表扫描
# 自查询 换成  join  ，条件比较 避免隐士类型转换
# 减少不必要的排序， 避免select * ，只查必要字段

# mysqldumpslow 也是慢查询分析工具，学习成本低
# 阶段	        工具/方法	                    目标
# 定位	        慢查询日志 + pt-query-digest	识别TOP 10高消耗SQL
# 分析	        EXPLAIN + 执行计划	            确认索引失效/全表扫描
# 优化实施	    索引优化 + SQL重写	            减少扫描行数与I/O
# 架构扩展	    分区表 → 分库分表	            突破单机性能瓶颈
# 长效预防	    PMM监控 + 定期OPTIMIZE TABLE	避免性能退化


# 主从知识点：https://mp.weixin.qq.com/s?__biz=MzkyMzU5Mzk1NQ==&mid=2247506396&idx=1&sn=dc6e6d488049d9449907e4dc3df3ecd1&source=41#wechat_redirect

# ----------------------主从复制过程------------------
# 主服务器（增删改）写入二进制日志（bin log）这个日志按照事务提交顺序记录
# 从服务器链接主服务器，下载二进制日志，写入中继日志（relay log），
# 从服务器，按准许读取中继日志，执行sql

#  ------------------------- 事务隔离级别 ---------------------

# MySQL 的事务隔离级别定义了在多个事务并发执行时，一个事务能看到其他事务的哪些数据更改，
#       以及如何避免由并发操作引发的数据一致性问题

        # 不可重复读 (Non-repeatable Read)：在同一个事务内，两次读取同一条记录，得到的结果不同。
        #       这通常是因为在两次读取之间，另一个事务修改并提交了该记录。
        # 脏读 (Dirty Read)：一个事务读取了另一个未提交事务修改的数据。
        #       如果那个未提交事务被回滚，那么第一个事务读取到的数据就是无效的“脏”数据。
        # 幻读 (Phantom Read)：在同一个事务内，两次执行相同的查询（通常是范围查询），返回的结果集行数不同。
        #       这通常是因为在两次查询之间，另一个事务插入或删除了符合该查询条件的记录并提交


# 读未提交 (READ UNCOMMITTED)： 最低的隔离级别。一个事务可以读取到其他事务尚未提交的修改。
# 存在的问题：
#         脏读：非常可能发生。
#         不可重复读：可能发生。
#         幻读：可能发生。
# 使用场景：极少使用，除非对数据一致性要求极低且追求最高并发性能（但通常风险远大于收益）。

# 读已提交 (READ COMMITTED)：一个事务只能读取到其他事务已经提交的修改。这是 Oracle 等许多数据库的默认级别。
# 解决的问题：避免了脏读
# 存在的问题：
#         不可重复读：在一个事务内，如果其他事务修改并提交了数据，再次读取同一记录会看到新值。
#         幻读：可能发生（因为新插入或删除的行是其他事务已提交的操作）。
# InnoDB 实现：通常使用每次语句执行时创建快照（Statement-Level Snapshot）的方式来实现
# 使用场景：对一致性有一定要求，能接受不可重复读和可能的幻读。比 REPEATABLE READ 锁争用可能少一些。



# 可重复读 (REPEATABLE READ)：InnoDB默认隔离级别。保证在同一个事务中，多次读取同一范围的数据会返回第一次查询所建立的快照结果。
#         即使其他事务修改或删除了这些数据并提交，该事务看到的仍然是“旧”数据。
#         特别注意：在 MySQL 的 InnoDB 中，这个级别通过 MVCC 也很大程度上避免了幻读（针对快照读）。

# 解决的问题：避免了 脏读/不可重复读（针对同一记录的多次读取）/幻读 (部分)
#         在快照读（普通的 SELECT 语句）的情况下，避免了幻读（因为基于第一次查询的快照）。
#         但在当前读（SELECT ... FOR UPDATE, SELECT ... LOCK IN SHARE MODE, UPDATE, DELETE）的情况下，仍然可能遇到幻读。
# InnoDB 通过 Next-Key Locks（临键锁）来防止当前读时的幻读，效果非常好，但并非100%在标准定义下杜绝（标准要求串行化才能杜绝）。

# InnoDB 实现：在事务第一次执行 SELECT 语句时创建快照，后续读操作都基于这个快照（除非使用当前读）。
# 使用场景：需要保证同一事务内读取数据的一致性（如账户余额检查）。在 MVCC 和 Next-Key Locks 的加持下，平衡了性能和数据一致性。



# 串行化 (SERIALIZABLE)：最高的隔离级别。强制所有事务按顺序一个接一个地执行。它通过在所有读取操作涉及的数据上加共享锁
#                 （SELECT ... LOCK IN SHARE MODE 的效果）来实现。
# 存在的问题：并发性能最低，锁冲突最多，可能导致大量超时和死锁。
# 使用场景：对数据一致性要求极高，且可以容忍极低的并发性能。例如涉及金融交易核心部分的某些操作。一般很少使用。


#  -------------------------MVCC  ---------------------

# Mysql中的innoDB,
#         通过在事务启动时创建数据的“快照”,让读操作不阻塞写操作，写操作也不阻塞读操作
#         同时实现了 SQL 标准中的 READ COMMITTED 和 REPEATABLE READ 隔离级别
#         不采用锁来控制事物的方式,
#         用于数据库中对数据库的并发访问,
#         是一种非堵塞、同时还可以解决脏读，幻读，不可重复读等事务隔离问题，
#         但不能解决更新丢失问题。
#         提高了读写事务的并发性能




# MySQL InnoDB 的 MVCC 通过结合隐藏字段（DB_TRX_ID, DB_ROLL_PTR）、
# Undo Log（回滚日志，存储历史版本） 和 Read View（定义可见性） 这三个核心组件，

# undo log日志 分为两种
# insert undo log：事务进行插入操作时产生、在事务回滚时需要，提交事务后可以被立即丢弃。
# update undo log：进行update、delete时产生的undo log、不仅在回滚事务时需要、在快照读时也需要。
#       所以不能随便删除，只有在快速读或事务回滚不涉及该日志时，对应的日志才会被purge线程统一清除


# Read View(读视图)
#         read view读视图就是在进行快照读时会产生一个read view视图、在该事务执行的快照读的那一刻，
#         会生成数据库系统当前的一个快照，记录并维护系统当前活跃事务的ID(当每个事务开启时，都会被分配一个ID,
#         这个ID是递增的，所以最新的事务，ID值越大)。说白了就是用来记录发生快照读那一刻所有的记录，
#         当你下次就算有执行新的事务记录改变了read view没变读出来的数据依然是不变的。

# 而隔离级别中的RR（可重复读）、和RC（提交读）不同就是差在快照读时
#         前者创建一个快照和Read View并且下次快照读时使用的还是同一个Read View所以其他事务修改数据对他是不可见的、解决了不可重复读问题。
#         后者则是每次快照读时都会产生新的快照和Read View、所以就会产生不可重复读问题


# 实现了高效的非阻塞读和不同隔离级别的语义。它允许读操作获取一个一致性的数据快照，
# 而无需等待写操作完成，同时写操作也能继续进行而无需阻塞所有读操作，这是现代数据库实现高性能、高并发的基石之一



# MVCC 的核心思想：

# 版本链： 对于每一行数据，InnoDB 会维护一个或多个历史版本（通过 Undo Log 实现）。

# 快照读： 当一个事务启动时，它会基于某个时间点创建一个“数据快照”（称为 Read View）。
        # 在这个事务执行过程中，所有的普通 SELECT 语句（非锁定读）都基于这个快照来读取数据，
        # 看到的是该快照创建时刻的数据状态（或满足可见性的历史版本），而不管之后其他事务是否修改或提交了这些数据。

# 当前读： 对于数据修改语句（INSERT, UPDATE, DELETE）以及加锁的 
        # SELECT（如 SELECT ... FOR UPDATE, SELECT ... LOCK IN SHARE MODE），
        # 它们读取的是数据的最新已提交版本，并且需要获取相应的锁。


# ​​READ UNCOMMITTED​​：不使用 MVCC，直接读取最新数据

# ​​READ COMMITTED​​： 每次 SELECT 都生成新的 Read View 能看到其他事务已提交的修改
    # 解决了脏读（Dirty Read），但可能出现不可重复读（Non-Repeatable Read）和幻读（Phantom Read）
# ​​REPEATABLE READ​​（InnoDB 默认）： 事务开始时生成一个 Read View，整个事务期间使用同一个 保证可重复读
# ​​SERIALIZABLE​​：不使用 MVCC，通过加锁实现

# Read View (读视图)：
# 它定义了当前事务在读取数据时，哪些版本的数据对它可见。它主要包含：
# m_ids： 生成 Read View 时，系统中活跃（已启动但未提交）的读写事务 ID 列表。
# min_trx_id： m_ids 中的最小值。
# max_trx_id： 生成 Read View 时，系统应该分配给下一个新事务的 ID（即当前最大事务 ID + 1）。
# creator_trx_id： 创建该 Read View 的事务自身的 ID（对于只读事务，该值为 0）。


# nnoDB 为每行记录添加了三个隐藏字段：
# DB_TRX_ID：6字节， 记录最后修改该行数据的事务 ID。
# DB_ROLL_PTR：7字节，回滚指针，指向该行的 undo log 记录 历史版本通过 DB_ROLL_PTR 串联起来形成一个版本链。
# DB_ROW_ID：6字节，隐藏的行ID（当没有主键时自动生成）

# Undo Log（回滚日志）是 MySQL InnoDB 存储引擎中实现事务原子性和 MVCC（多版本并发控制）的关键组件
#           主要记录事务发生前的数据状态
                    # 事务回滚时恢复数据
                    # 实现 MVCC 读取一致性视图
                    # 提供事务隔离性




# SELECT 操作流程
# 当执行 SELECT 时，InnoDB 会创建一个 Read View
#     检查每行数据的 DB_TRX_ID
#     根据以下规则判断数据版本是否可见：
#     如果 DB_TRX_ID < min_trx_id：可见（事务已提交） 说明该行数据的修改事务在创建 Read View 之前就已经提交了。可见
#         如果 DB_TRX_ID > max_trx_id：不可见（事务还未开始）  
#                       说明该行数据是由一个在创建 Read View 之后才启动的事务修改的  
#                       不可见  (应该去版本链中找更旧的版本)

#         如果 min_trx_id ≤ DB_TRX_ID ≤ max_trx_id：
#               如果 DB_TRX_ID 在 m_ids 中：不可见（事务未提交） 说明修改该行数据的事务在创建 Read View 时仍活跃，
#                               不可见 ❌ (应该去版本链中找更旧的版本)

#               否则：可见（事务已提交） 说明修改该行数据的事务在创建 Read View 时已经提交。可见 ✅

#        DB_TRX_ID == creator_trx_id  说明该行数据是当前事务自己修改的。 可见 ✅


# INSERT：创建新版本，设置 DB_TRX_ID 为当前事务ID
# DELETE：逻辑删除，设置删除标记
# UPDATE：创建新版本，旧版本通过 DB_ROLL_PTR 指向 undo log

# 特性	        Undo Log	                Redo Log
# 目的	        回滚事务/MVCC	            崩溃恢复
# 内容	        修改前的数据	             修改后的数据
# 生命周期	    短(事务结束)或长(MVCC)	     短(写入数据文件后可覆盖)
# 存储位置	    系统表空间/独立undo空间	     固定大小的循环文件
# 写入时机	    事务过程中	                事务提交前



# 数据库主从概念、优点、用途：主库对外提供读写的操作，从库对外提供读的操作； 主数据同步到从

# 高可用，实时灾备，用于故障切换。比如主库挂了，可以切从库。
# 读写分离，提供查询服务，减少主库压力，提升性能
# 备份数据，避免影响业务

# 主库的更新SQL(update、insert、delete)被写到binlog
# 从库发起连接，连接到主库。
# 此时主库创建一个binlog dump thread，把bin log的内容发送到从库。
# 从库启动之后，创建一个I/O线程，读取主库传过来的bin log内容并写入到relay log
# 从库还会创建一个SQL线程，从relay log里面读取内容，从ExecMasterLog_Pos位置开始执行读取到的更新事件，将更新内容写入到slave的db



# 主主、两台都是主数据库，同时对外提供读写操作，数据存在双向同步
# 主备：读写主， 主同步备


# binlog 日志有三种格式，分别是statement，row和mixed
# 如果是statement格式，binlog记录的是SQL的原文，如果主库和从库选的索引不一致，可能会导致主库不一致。
# 把binlog格式修改为row。row格式的binlog日志，记录的不是SQL原文，而是两个event:Table_map 和 Delete_rows。
        # Table_map event说明要操作的表，Delete_rows event用于定义要删除的行为，
        # 记录删除的具体行数。row格式的binlog记录的就是要删除的主键ID信息，因此不会出现主从不一致的问题
            # ----------数据量大时消耗io------------
# mixed格式的binlog。所谓的mixed格式其实就是row和statement格式混合使用，当MySQL判断可能数据不一致时，就用row格式，否则使用就用statement格式。






# 数据库主从延迟的原因与解决方案
        # 主执行完事务写入 binlog  -------   从库执行完事务  这期间的时间为延迟
        # 1. 机器见的性能差异
        # 2. 大事务
        # 3. 从数据库访问量大，导致执行同步慢（多加几个从库）
        # 4. 网络延迟



# 主备高可用
# 主 --------备
# 主挂-------读写备
# 主启动变成备---------------备升级成主
# 优点：一个机器故障了可以自动切换，操作比较简单。
# 缺点：只有一个库在工作，读写压力大，未能实现读写分离，并发也有一定限制



# 主从也是类似： 可以增加多个（3个左右）备



# MariaDB同步多主机集群
# 代理层实现负载均衡，多个数据库可以同时进行读写操作；各个数据库之间可以通过Galera Replication方法进行数据同步，每个库理论上数据是完全一致的
# 优点：读写的并发度都明显提升，可以任意节点读写，可以自动剔除故障节点，具有较高的可靠性。
# 缺点：数据量不支持特别大。要避免大事务卡死，如果集群节点一个变慢，其他节点也会跟着变慢。


# # 数据库中间件
# 负载均衡 + mycat-----------》 练到 mysql集群
# 架构描述：mycat分片存储，每个分片配置一主多从的集群。
# 优点：解决高并发高数据量的高可用方案
# 缺点：维护成本比较大。





# 事务核心 (ACID)： Redo Log (持久性) + Undo Log (原子性/一致性) + 锁机制 (隔离性) 共同保障。
# 复制核心： Binlog (主库产生) -> Relay Log (从库接收) -> SQL 线程重放 (从库执行)。
# 恢复核心： Redo Log (重做已提交) + Undo Log (回滚未提交) + Binlog (PITR)。
# 性能与安全权衡： Binlog、慢查询、通用日志的开启会影响 I/O 性能，需根据业务需求和安全审计要求配置。
# 日志管理： 所有日志文件都需要定期监控、备份（尤其是 Binlog）、轮转和清理，防止磁盘空间耗尽。





# 一个索引包含了查询语句中 SELECT 子句和 WHERE 子句（以及 GROUP BY、ORDER BY 等）所需的所有字段。 
# 换句话说，MySQL 引擎只需要扫描这个索引本身就能获取查询所需的所有数据，
# 而无需再回到原始数据表（通常是主键索引对应的数据页）中去查找数据行


# EXPLAIN 语句查看查询的执行计划。如果 Extra 列中显示 Using index condition
# 索引下推优化改变了这个流程： 
# 它将 索引中包含的列 的 WHERE 条件（即使这些条件不能完全用索引来查找，只能用来过滤）“下推”到存储引擎层去执行。
# 存储引擎可以在使用索引检索数据的同时，直接利用这些下推的条件在索引内部进行初步过滤，
# 只将真正满足所有索引条件下推条件的行返回给服务器层。

# mysql 的语句优化和  索引相关
# 分析sql语句，原则是只查询需要的数据，尽量不用子查询，join的时候使用小表驱动大表，使用联合查询替换 in 和not in
# 索引包括 主见索引，唯一索引， 单列索引 还有组合索引，索引的维护是需要占用空间的，对于频繁修改的字段不适宜加索引
# 索引使用与 where ， group by  order by，经常查询少有修改的字段，修改较多的字段不适宜加索引，遵循最左匹配原则，
# 注意索引失效，左模糊查询，索引参与计算、隐士类型转换，出现 or in这些，最好的就是覆盖索引这样能避免回表

# 索引下推：
# 传统的查询是根据索引查询满足索引最左前缀匹配的原则，返回给mysql服务层，然后服务层再根据后置条件对数据进行过滤
# 索引下推是将where中的所有所有包含索引的列下推到存储引擎层，存储引擎不仅根据索引条件进行匹配，还根据索引进行过滤
# 最后只将复合条件的数据返回给服务层，
# 这样显著减少了需要回表读取完整数据的行数，也减少了传输到服务器层的数据量，降低了服务器层的过滤负担



# 高并发查询插入问题： 主键冲突
# insert into table (column_list) values(value_list) on duplicate key update k1 = v1, k2=v2



# 幂等性问题：

#         非并发场景：
#                 先 select 看看存在与否  ---------- 已经存在的情况做 update  否则 使用 inser

# 悲观锁：锁住当前行， select * from user where id = 1 for update;  引擎必须是 innodb， id必须是主键或唯一索引，不然会锁整张表
# 乐观锁：给表增加 timestemp字段 或 version字段
#         update user set age=age+1, version=version+1 where id=1  and version = 1;
#         返回的数据变更条数如果等于0 说明没有变更
        # --------- 这种情况也可以应用在某一个存在状体机制的字段， 如 status 1，2，3 分别代表订单的几种状态
        #                 update order set status = 3 where id= 1 and status = 2;

# 防止重复数据产生在表中加入唯一索引

# 建立防重复表：
#         使用防重复字符按建立一张表： 如只有 id 和 fingerid
#         防重复表插入成功在去操作数据表
#         两张表必须在同一个数据库，且必须在同一个事务执行



# 分表：一般都是通过主键分
# id 范围分表， 结合 id 取模分表

# 分表导致都扩散问题：如果读的数据不是 主键索引 而是 其他索引，那么就需要都多张表，产生读扩散问题
# 新建一个表将普通索引定义成主键，原来的主键索引改为普通索引

